/*
 * Team Theta
 * CTC Office
 * CTC Class
 * Yuxin Liu
 */
package edu.pitt.coe1186.theta.ctc;

import edu.pitt.coe1186.theta.util.Global;
import java.util.List;
import javafx.animation.PathTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Duration;

public class CTC extends Application {
    Scene scene;
    Label warning;

    // Areas
    static VBox scheduleBox;
    static VBox mapBox;
    static VBox modeBox;
    static VBox trainBox;
    static VBox trackBox;
    static VBox throughputBox;
    static VBox statusBox;
    static VBox debugBox;

    static Button btnNormal;
    static Button btnTest;
    static Button btnManual;
    static Button btnFaster;
    
    static Button btnEnableTrack;
    static Button btnDisableTrack;

    static Button btnAddTrain;
    static Button btnRemoveTrain;
    static Button btnSetAuthority;
    static Button btnSetSpeed;
    static Label debug;
    static Stage dialogStage;
    Stage stage;
    static Group trace;
    Global g;
    static PathTransition transition;
    static PathTransition pathTransition;
    static Path path;
    static Circle circle;
    static float k;
    
    static PathTransition transition2;
    static PathTransition pathTransition2;
    static Path path2;
    static Circle circle2;

    static int train_number;
    static int train_selected;

    static Label lbLines;
    static Label lbTrains;
    static Label lbPasenggers;
    static Label lbTrainLenth;
    static Label lbTrainWeight;
    static Label lbTrainPasenggers;


    
    @Override 
    public void start(Stage primaryStage) {
        Group root = new Group();
        scene = new Scene(root, 1200, 830, Color.BLACK);
        primaryStage.setScene(scene);
        primaryStage.setTitle("CTC Office");
        VBox vbox = new VBox();
        g = Global.getInstance();
        stage = primaryStage;
        train_number = 0;
        train_selected = 0;
        
        /********************
         * debug label
         ********************/
        warning = (Label)debugLabel();
        root.getChildren().add(warning);
        
        /********************
         * menubar
         ********************/
        MenuBar menu = (MenuBar)Menu(primaryStage);
        vbox.getChildren().add(menu);
        
        /********************
         * dividing UI
         ********************/
        // main pane 
        SplitPane splitPane = new SplitPane(); 
        splitPane.prefWidthProperty().bind(scene.widthProperty()); 
        splitPane.prefHeightProperty().bind(scene.heightProperty()); 
        // left pane
        SplitPane leftPane = new SplitPane(); 
        leftPane.setOrientation(Orientation.VERTICAL);
        leftPane.prefWidthProperty().bind(scene.widthProperty()); 
        leftPane.prefHeightProperty().bind(scene.heightProperty()); 
        //right pane
        SplitPane rightPane = new SplitPane();
        rightPane.setOrientation(Orientation.VERTICAL);
        rightPane.prefWidthProperty().bind(scene.widthProperty());
        rightPane.prefHeightProperty().bind(scene.heightProperty());
        // lower left pane 
        SplitPane lowerLeftPane = new SplitPane(); 
        lowerLeftPane.prefWidthProperty().bind(scene.widthProperty()); 
        lowerLeftPane.prefHeightProperty().bind(scene.heightProperty()); 
        
        // Areas
        debugBox = new VBox();
        mapBox = new VBox();
        modeBox = new VBox();
        trainBox = new VBox();
        trackBox = new VBox();
        throughputBox = new VBox();
        statusBox = new VBox();
        scheduleBox = new VBox();setTab();
        
        //mapBox.getChildren().add(new Text("Map"));
        setDebugBox();
        setMap();
        setTrackBox();
        setTrainBox();
        setModeBox();
        throughputBox.getChildren().add(new Text("Throughput"));
        setThroughputBox();
        statusBox.getChildren().add(new Text("System Status"));
        scheduleBox.getChildren().add(new Text("Train Schedule/Status"));
        
        
        // Building Hierachy
        lowerLeftPane.getItems().add(modeBox);
        lowerLeftPane.getItems().add(trainBox);
        lowerLeftPane.getItems().add(trackBox);

        leftPane.getItems().add(debugBox);
        leftPane.getItems().add(mapBox);
        leftPane.getItems().add(lowerLeftPane);
        
        rightPane.getItems().add(throughputBox);
        rightPane.getItems().add(statusBox);
        rightPane.getItems().add(scheduleBox);
        
        splitPane.getItems().add(leftPane);
        splitPane.getItems().add(rightPane);
        
        // set divider
        splitPane.getDividers().get(0).setPosition(950.0/1200.0);
        lowerLeftPane.getDividers().get(0).setPosition(317.0/950.0);
        lowerLeftPane.getDividers().get(1).setPosition(2*317.0/950.0);
        leftPane.getDividers().get(0).setPosition(30.0/650.0);
        leftPane.getDividers().get(1).setPosition(520.0/650.0);
        rightPane.getDividers().get(0).setPosition(250.0/650.0);
        rightPane.getDividers().get(1).setPosition(450.0/650.0);
       
        vbox.getChildren().add(splitPane);
        root.getChildren().add(vbox);
        
        
        
        // Button CTC
        Button submit = new Button("Login");
        submit.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent e) {
                
            }
        });
        submit.setLayoutX(scene.getWidth()*0.60);
        submit.setLayoutY(scene.getHeight()*0.55);
        //root.getChildren().add(submit);
        

        
        
        primaryStage.show();
        //applyAnimation(trace); 


}
    
    
    Node text(String text){
        
        Label label1 = new Label(text);
        label1.setTextFill(Color.rgb(255, 255, 255)); 
        TextField textField = new TextField ();
        HBox hb = new HBox();
        hb.getChildren().addAll(label1, textField);
        hb.setSpacing(20);
        hb.setLayoutX(scene.getWidth()*0.4 );
        hb.setLayoutY(scene.getHeight()*0.45);
        
        
        return hb;
    }
    
    Node pswText(String text){
        Label label1 = new Label(text);
        label1.setTextFill(Color.rgb(255, 255, 255)); 
        PasswordField textField = new PasswordField ();
        HBox hb = new HBox();
        hb.getChildren().addAll(label1, textField);
        hb.setSpacing(20);
        hb.setLayoutX(scene.getWidth()*0.4 );
        hb.setLayoutY(scene.getHeight()*0.45);
        
        
        return hb;
    }
    
    Node Menu(Stage primaryStage){
        MenuBar menuBar = new MenuBar();

        // File menu - new, save, exit
        Menu menu = new Menu("File");
        menu.getItems().add(new MenuItem("New"));
        menu.getItems().add(new MenuItem("Save"));
        menu.getItems().add(new SeparatorMenuItem());
        menu.getItems().add(new MenuItem("Exit"));

        menuBar.getMenus().add(menu);

        // Cameras menu - camera 1, camera 2
        Menu tools = new Menu("Cameras");
        tools.getItems().add(CheckMenuItemBuilder.create()
                .text("Show Camera 1")
                .selected(true)
                .build());

        tools.getItems().add(CheckMenuItemBuilder.create()
                .text("Show Camera 2")
                .selected(true)
                .build());
        //menuBar.getMenus().add(tools);


        // Alarm
        Menu alarm = new Menu("Alarm");
        ToggleGroup tGroup = new ToggleGroup();
        RadioMenuItem soundAlarmItem = RadioMenuItemBuilder.create()
                .toggleGroup(tGroup)
                .text("Sound Alarm")
                .build();
        RadioMenuItem stopAlarmItem = RadioMenuItemBuilder.create()
                .toggleGroup(tGroup)
                .text("Alarm Off")
                .selected(true)
                .build();

        alarm.getItems().add(soundAlarmItem);
        alarm.getItems().add(stopAlarmItem);

        Menu contingencyPlans = new Menu("Contingent Plans");
        contingencyPlans.getItems().add(new CheckMenuItem("Self Destruct in T minus 50"));
        contingencyPlans.getItems().add(new CheckMenuItem("Turn off the coffee machine "));
        contingencyPlans.getItems().add(new CheckMenuItem("Run for your lives! "));

        alarm.getItems().add(contingencyPlans);
        //menuBar.getMenus().add(alarm);
        menuBar.prefWidthProperty().bind(primaryStage.widthProperty());
        return menuBar;
    }
    
    Node debugLabel(){
        Label l = new Label("Hello World!");
        l.setTextFill(Color.rgb(255, 255, 255));
        l.setScaleX(2);
        l.setScaleY(2);
        l.setLayoutX(scene.getWidth()*0.45);
        l.setLayoutY(scene.getHeight()*0.3);
        
        return l;
    }
   
    void setTab(){
        TabPane tabPane = new TabPane();
        BorderPane borderPane = new BorderPane();

        // generate tabs
        for (int i = 0; i < 2; i++) {
            Tab tab = new Tab();
            if(i==0){ tab.setText("Schedule    ");
                VBox hbox = new VBox();
                hbox.getChildren().add(new Label("Tab" + i));
                hbox.setAlignment(Pos.CENTER);
                tab.setContent(hbox);
            }
            else {  
                tab.setText("Train Status");
                VBox hbox = new VBox();
                lbTrainLenth = new Label("Train Lenth: 0");
                lbTrainWeight = new Label("Train Wight: 0");
                lbTrainPasenggers = new Label("Train Pasenggers: 0");
                hbox.getChildren().add(lbTrainLenth);
                hbox.getChildren().add(lbTrainWeight);
                hbox.getChildren().add(lbTrainPasenggers);
                hbox.setAlignment(Pos.CENTER);
                tab.setContent(hbox);
            }
            
            tabPane.getTabs().add(tab);
        }

        // add tab pane
        borderPane.setCenter(tabPane);

        // bind to take available space
        borderPane.prefHeightProperty().bind(scheduleBox.heightProperty());
        borderPane.prefWidthProperty().bind(scheduleBox.widthProperty());
        
        scheduleBox.getChildren().add(borderPane);
        
    }
    void setDebugBox(){
        debug = new Label("debug");
        debug.setFont(new Font("Arial", 30));
        debugBox.getChildren().add(debug);
    }
    
    void setMap(){
        ImageView iv = new ImageView(new Image(getClass().getResourceAsStream("images/track.jpg")));
         //lowerLeftPane.prefWidthProperty().bind(scene.widthProperty()); 
        //lowerLeftPane.prefHeightProperty().bind(scene.heightProperty()); 
        iv.setFitWidth(958);
        iv.setFitHeight(620);
        iv.setPreserveRatio(false);
        iv.setSmooth(true);
        trace = new Group();
        trace.getChildren().add(iv);
        //mapBox.getChildren().add(iv);
        mapBox.getChildren().add(trace);
    }
    
    void setModeBox(){
        GridPane grid =new GridPane();
        btnNormal = new Button("Normal ");
        btnTest   = new Button("Test     ");
        btnManual = new Button("Mannual");
        btnFaster = new Button("10 X      ");
        
        
        btnNormal.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                debug.setText("Normal mode");
                if(k>2){
                    transition = generatePathTransition(circle, path,1);
                    transition2 = generatePathTransition(circle2, path2,1);
                }   
                transition.play();
                transition2.play();
            }
        });

        btnTest.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                debug.setText("Test mode");
            }
        });

        btnManual.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                transition.pause();
                transition2.pause();
                debug.setText("Mannual mode");
            }
        });

        btnFaster.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                debug.setText("10X mode");
                transition = generatePathTransition(circle, path,3);
                transition.play(); 
                transition2 = generatePathTransition(circle2, path2,3);
                transition2.play();
            }
        });
        
        btnNormal.setScaleX(2);
        btnNormal.setScaleY(2);
        btnTest.setScaleX(2);
        btnTest.setScaleY(2);
        btnManual.setScaleX(2);
        btnManual.setScaleY(2);
        btnFaster.setScaleX(2);
        btnFaster.setScaleY(2);
        
        grid.add(btnNormal, 1, 1);
        grid.add(btnTest, 2, 1);
        grid.add(btnManual, 1, 2);
        grid.add(btnFaster, 2, 2);
        
        grid.setVgap(30);
        grid.setHgap(65);
        
        modeBox.getChildren().add(grid);
    }

    void setTrackBox(){
        GridPane grid = new GridPane();
        btnEnableTrack = new Button("Enable Track");
        btnDisableTrack = new Button("Disable Track");

        btnEnableTrack.setScaleX(1.5);
        btnEnableTrack.setScaleY(1.5);
        btnDisableTrack.setScaleX(1.5);
        btnDisableTrack.setScaleY(1.5);

        btnEnableTrack.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                debug.setText("Enable Track");
            }
        });

        btnDisableTrack.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                debug.setText("Disable Track");
            }
        });

        grid.add(btnEnableTrack, 1, 1);
        grid.add(btnDisableTrack, 2, 1);
        grid.setVgap(30);
        grid.setHgap(40);

        trackBox.getChildren().add(grid);

    }
    void setThroughputBox(){
        lbLines = new Label("Lines Active: 0");
        lbTrains = new Label("Trains: 0");
        lbPasenggers = new Label ("Pasenggers: 0");

        throughputBox.getChildren().add(lbLines);
        throughputBox.getChildren().add(lbTrains);
        throughputBox.getChildren().add(lbPasenggers);
        
    }

    void setTrainBox(){
        GridPane grid = new GridPane();
        btnAddTrain = new Button("Add Train");
        btnRemoveTrain = new Button("Remove Train");
        btnSetAuthority = new Button("Set authority");
        btnSetSpeed = new Button("Set Speedlimit");

        btnAddTrain.setScaleX(1.5);
        btnAddTrain.setScaleY(1.5);
        btnRemoveTrain.setScaleX(1.5);
        btnSetAuthority.setScaleX(1.5);
        btnSetSpeed.setScaleX(1.5);
        btnRemoveTrain.setScaleY(1.5);
        btnSetAuthority.setScaleY(1.5);
        btnSetSpeed.setScaleY(1.5);

        btnAddTrain.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                train_number++;
                debug.setText("Add Train " + train_number);
                
                applyAnimation(trace); 
                update();
                
            }
        });

        btnRemoveTrain.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                
                debug.setText("Remove Train"+ train_number);
                if(train_number==1){
                    trace.getChildren().remove(circle);
                }else if(train_number==2){
                    trace.getChildren().remove(circle2);
                }
                train_number--;
                
                update();
            }
        });

        btnSetAuthority.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                debug.setText("Set Authority");
            }
        });

        btnSetSpeed.setOnAction(new EventHandler<ActionEvent>() {
            final Button btnOK = new Button("OK");
            final Button btnCancel = new Button("Cancel");
            final Label label1 = new Label("Set speed limit:"); 
            
            
            @Override
            public void handle(ActionEvent e) {
                debug.setText("Set Speedlimit");
                g.setDialog("speed");
                //Dialog d = new Dialog();
                dialogStage = new Stage();
                //d.start(dialogStage);
                
                final TextField textField = new TextField ();
               
                
                dialogStage.initModality(Modality.WINDOW_MODAL);
                dialogStage.setScene(new Scene(VBoxBuilder.create().
                children(label1,textField,btnOK,btnCancel).
                alignment(Pos.CENTER).padding(new Insets(5)).build()));
                
                btnOK.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent e) {
                        String id = textField.getText();
                        debug.setText("Set Speedlimit to "+id);
                        dialogStage.close();
                    }
                });

                btnCancel.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent e) {
                        
                        dialogStage.close();
                    }
                });

                dialogStage.show();
                //dialogStage.close();
               
                //*/

            }
        });

        grid.add(btnAddTrain, 1, 1);
        grid.add(btnRemoveTrain, 2, 1);
        grid.add(btnSetAuthority, 1, 2);
        grid.add(btnSetSpeed, 2, 2);
        
        grid.setVgap(30);
        grid.setHgap(45);
        
        trainBox.getChildren().add(grid);


    
    }

    /*****************************************************/
    /*****************************************************/
    /*****************************************************/
    /*****************************************************/
    /*****************************************************/
    /*****************************************************/
    /**
    * Generate Path upon which animation will occur.
    * 
    * @param pathOpacity The opacity of the path representation.
    * @return Generated path.
    */
   private Path generateCurvyPath(final double pathOpacity)
   {
      final Path path = new Path();
      path.getElements().add(new MoveTo(400,20));
      path.getElements().add(new QuadCurveTo(120, -10, 180, 200));
      //path.getElements().add(new CubicCurveTo(0, 120, 0, 240, 380, 240));
      path.setOpacity(pathOpacity);
      return path;
   }
   
   private Path generateLinePath(final double pathOpacity)
   {
      final Path path = new Path();
      path.getElements().add(new MoveTo(440,200));
      path.getElements().add(new LineTo(440, 400));
      //path.getElements().add(new CubicCurveTo(0, 120, 0, 240, 380, 240));
      path.setOpacity(pathOpacity);
      return path;
   }


   /**
    * Generate the path transition.
    * 
    * @param shape Shape to travel along path.
    * @param path Path to be traveled upon.
    * @return PathTransition.
    */
   private PathTransition generatePathTransition(final Shape shape, final Path path, float time)
   {
      k = time;
      pathTransition = new PathTransition();
      pathTransition.setDuration(Duration.seconds(8.0/time));
      pathTransition.setDelay(Duration.seconds(2.0/time));
      pathTransition.setPath(path);
      pathTransition.setNode(shape);
      pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
      pathTransition.setCycleCount(Timeline.INDEFINITE);
      pathTransition.setAutoReverse(true);
      return pathTransition;
   }

   /**
    * Determine the path's opacity based on command-line argument if supplied
    * or zero by default if no numeric value provided.
    * 
    * @return Opacity to use for path.
    */
   private double determinePathOpacity()
   {
      final Parameters params = getParameters();
      final List<String> parameters = null;//params.getRaw();
      double pathOpacity = 0.0;
      
      return pathOpacity;
   }

   /**
    * Apply animation, the subject of this class.
    * 
    * @param group Group to which animation is applied.
    */
   private void applyAnimation(final Group group)
   {
       if(train_number==1){
        circle = new Circle(20, 20, 15);
        circle.setFill(Color.DARKRED);
        circle.setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent e) {
                    debug.setText("Train 1 selected");
                    train_selected = 1;
                    update();

                }
            });
        path = generateCurvyPath(determinePathOpacity());
        group.getChildren().add(path);
        group.getChildren().add(circle);
        //group.getChildren().add(new Circle(20, 20, 5));
        //group.getChildren().add(new Circle(380, 240, 5));
        transition = generatePathTransition(circle, path,1);
        transition.play(); 
       }
       else{
           circle2 = new Circle(20, 20, 15);
            circle2.setFill(Color.BLUEVIOLET);
            circle2.setOnMouseClicked(new EventHandler<MouseEvent>() {
                    @Override
                    public void handle(MouseEvent e) {
                        debug.setText("Train 2 selected");
                        train_selected = 2;
                        update();

                    }
                });
            path2 = generateLinePath(determinePathOpacity());
            group.getChildren().add(path2);
            group.getChildren().add(circle2);
            //group.getChildren().add(new Circle(20, 20, 5));
            //group.getChildren().add(new Circle(380, 240, 5));
            transition2 = generatePathTransition(circle2, path2,1);
            transition2.play(); 
           
           
       }
      
   }

   void update(){
    if(train_number==1){
        lbLines.setText("Lines Active: 1");
        lbTrains.setText("Trains: 1");
        lbPasenggers.setText("Pasenggers: 300");
        
    }else if (train_number==2) {
        lbLines.setText("Lines Active: 2");
        lbTrains.setText("Trains: 2");
        lbPasenggers.setText("Pasenggers: 500");
        

    }

    if(train_selected==1){
        lbTrainLenth.setText("Train Lenth: 10");
        lbTrainWeight.setText("Train Wight: 45 tons");
        lbTrainPasenggers.setText("Train Pasenggers: 300");

    }else if(train_selected==2){
        lbTrainLenth.setText("Train Lenth: 5");
        lbTrainWeight.setText("Train Wight: 25 tons");
        lbTrainPasenggers.setText("Train Pasenggers: 200");

    }


   }

   

    
}


    

   

//*/
